// 版权所有2009年围棋作者。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package objabi

import (
	"internal/buildcfg"
	"os"
	"path/filepath"
	"strings"
)

// WorkingDir返回当前工作目录
// （或“/？”，如果无法识别目录），
// 使用“/”作为分隔符。
func WorkingDir() string {
	var path string
	path, _ = os.Getwd()
	if path == "" {
		path = "/???"
	}
	return filepath.ToSlash(path)
}

// AbsFile返回给定目录中文件的绝对文件名，
// 由“重写”参数重写。
// 对于未写入的路径，AbsFile将前导$GOROOT前缀重写为文字“$GOROOT”。
// 如果结果路径为空字符串，则结果为“？”。
// None
// “重写”论点是一个错误-单独的重写列表。
// 每次重写的形式为“prefix”或“prefix=>replace”，
// 其中前缀必须与路径元素的前导序列匹配
// 或者被完全移除，或者被替换物替换。
func AbsFile(dir, file, rewrites string) string {
	abs := file
	if dir != "" && !filepath.IsAbs(file) {
		abs = filepath.Join(dir, file)
	}

	abs, rewritten := ApplyRewrites(abs, rewrites)
	if !rewritten && hasPathPrefix(abs, buildcfg.GOROOT) {
		abs = "$GOROOT" + abs[len(buildcfg.GOROOT):]
	}

	if abs == "" {
		abs = "??"
	}
	return abs
}

// ApplyRewrites返回给定目录中文件的文件名，
// 由“重写”参数重写。
// None
// “重写”论点是一个错误-单独的重写列表。
// 每次重写的形式为“prefix”或“prefix=>replace”，
// 其中前缀必须与路径元素的前导序列匹配
// 或者被完全移除，或者被替换物替换。
func ApplyRewrites(file, rewrites string) (string, bool) {
	start := 0
	for i := 0; i <= len(rewrites); i++ {
		if i == len(rewrites) || rewrites[i] == ';' {
			if new, ok := applyRewrite(file, rewrites[start:i]); ok {
				return new, true
			}
			start = i + 1
		}
	}

	return file, false
}

// applyRewrite将重写应用于路径，
// 返回重写的路径和布尔值
// 指示是否应用了重写。
func applyRewrite(path, rewrite string) (string, bool) {
	prefix, replace := rewrite, ""
	if j := strings.LastIndex(rewrite, "=>"); j >= 0 {
		prefix, replace = rewrite[:j], rewrite[j+len("=>"):]
	}

	if prefix == "" || !hasPathPrefix(path, prefix) {
		return path, false
	}
	if len(path) == len(prefix) {
		return replace, true
	}
	if replace == "" {
		return path[len(prefix)+1:], true
	}
	return replace + path[len(prefix):], true
}

// s是否将t作为路径前缀？
// 也就是说，s==t还是s以t开头，后跟斜杠？
// 为了便于移植，我们允许ASCII大小写折叠，因此hasPathPrefix（“a/b/c”、“a/b”）是正确的。
// 类似地，我们允许斜杠折叠，因此hasPathPrefix（“a/b/c”、“a\\b”）为true。
// 我们不允许完全的Unicode大小写折叠，以免引起更多的混乱
// 还是弊大于利。（举例说明可能出现的问题，
// 见http：
func hasPathPrefix(s string, t string) bool {
	if len(t) > len(s) {
		return false
	}
	var i int
	for i = 0; i < len(t); i++ {
		cs := int(s[i])
		ct := int(t[i])
		if 'A' <= cs && cs <= 'Z' {
			cs += 'a' - 'A'
		}
		if 'A' <= ct && ct <= 'Z' {
			ct += 'a' - 'A'
		}
		if cs == '\\' {
			cs = '/'
		}
		if ct == '\\' {
			ct = '/'
		}
		if cs != ct {
			return false
		}
	}
	return i >= len(s) || s[i] == '/' || s[i] == '\\'
}
